<template>
    <el-dialog title="请选择" :visible.sync="transferDialog" append-to-body height="450px" width="65%" custom-class="transferForm" :before-close="cancelDialog">
      <div>
        <div class="transferForm-box">
          <div class="transferLeft transferBox">
            <div style="height: 100%">
              <div class="transferBox-title">
                <el-form @keyup.native.enter="handleFilter">
                  <el-row style="margin-top: 26px">
                    <el-col :span="16">
                      <el-form-item label-width="50px" label="检索:">
                        <el-input v-model="filterText" placeholder="请输入检索内容" clearable></el-input>
                      </el-form-item>
                    </el-col>
                    <el-col :span="4">
                      <el-form-item label-width="10px">
                        <el-button @click="handleFilter">检索</el-button>
                      </el-form-item>
                    </el-col>
                    <el-col :span="4">
                      <el-form-item label-width="10px">
                        <el-button @click="filterReset">重置</el-button>
                      </el-form-item>
                    </el-col>
                  </el-row>
                </el-form>
              </div>
              <div class="transferBox-con">
                <vue-easy-tree ref="tree" v-if="refreshTable" v-loading="loading" :data="data" :props="defaultProps"
                         :default-expanded-keys="defaultExpandedKeys" :check-strictly="!multiple" node-key="id"
                         :default-expand-all="isExpand" check-on-click-node show-checkbox  virtual-scroll :height="autoHeight"
                         @check-change="validateSelection" :filter-node-method="filterNode"></vue-easy-tree>
              </div>
            </div>
          </div>
          <div class="transferRight transferBox">
            <div class="transferBox-title">{{(!multiple ? '仅可选一项 ': '已选择 ') + '(双击取消选择)'}}</div>
            <div class="transferBox-con">
              <el-row v-for="item in teamActiveList" :key="item.id" :class="{current: teamActiveCurrent === item.id}">
                <div @click="teamActiveListClick(item)" @dblclick="removeDblclickItem">
                  <el-button style="margin-left: 2%; margin-right: 2%; border: none; width: 96%; text-align: left">{{ item.name }}</el-button>
                </div>
              </el-row>
            </div>
          </div>
          <div class="transferArrow">
            <i class="arrowIcon el-icon-top" @click="moveClick('top')"></i>
            <i class="arrowIcon el-icon-bottom" @click="moveClick('bottom')"></i>
            <i class="arrowIcon el-icon-delete" @click="clearTeamActiveList"></i>
          </div>
        </div>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="confirm">确定</el-button>
        <el-button @click="cancelDialog">关闭</el-button>
      </span>
    </el-dialog>
</template>

<script>

import VueEasyTree from "@wchbrad/vue-easy-tree";
import {
  fetchTreeByType,
  fetchTree,
  fetchTreeByTypes,
} from "@/api/admin/dept";
import {
  listAuditedUserTree,
  listAuditUserTree,
  listUserTreeByJobCategory,
  listUserTreeByDeptId,
  listUserTreeByDeptIds,
} from "@/api/admin/user";

export default {
  components: {
    VueEasyTree
  },
  data() {
    return {
      defaultProps: {
        children: 'children',
        label: 'name'
      },
      data: [],
      nodeMap: new Map(),
      companyList: [],
      departmentList: [],
      unitList: [],
      teamList: [],
      planList:[],
      teamActiveList: [],
      teamActiveCurrent: null,
      companyActiveList: [],
      departmentActiveList: [],
      userActiveList: [],
      unitActiveList: [],
      planActiveList: [],
      transferType: '',
      defaultExpandedKeys: [],
      treeClickCount: 0,
      refreshTable: true,
      filterText: '',
      isExpand: true,
      loading: false,
      labelCache: {},
      autoHeight: '100%',
    }
  },
  props: {
    multiple: {
      type: Boolean,
      default: true
    },
    transferDialog: {
      type: Boolean,
      default: false
    },
    currentval: {
      type: Array,
      default: ()=>[]
    },
    transferDialogType: {
      type: String,
      default: 'user'
    }, // user:人员，users:多部门人员，unit:职位，department:部门,company:单位,plan:计划,auditUser:审计
    transferCurrent: {
      type: Object,
      default: ()=> null
    },
  },
  watch: {
    filterSingleText(val) {
      this.teamList = this.teamList.filter(item => item.name.indexOf(val) > -1);
    },
    currentval(val) {
      this.teamActiveList = val
    },
    transferDialog(val) {
      this.loading = true;
      if (val) {
        this.data = [];
        switch (this.transferDialogType) {
          case 'company':
            if (this.transferCurrent.type) {
              fetchTreeByType({type: this.transferCurrent.type}).then((res) => {
                this.loading = false
                this.data = res.data.data;
                this.buildLabelCache(this.data);
              });
            } else {
              fetchTree().then((res) => {
                this.loading = false
                this.data = res.data.data;
                this.buildLabelCache(this.data);
              });
            }
            break;
          case 'user':
            listUserTreeByDeptId({deptId: this.transferCurrent.deptId}).then((res) => {
              this.loading = false
              this.data = res.data.data;
              this.buildLabelCache(this.data);
            });
            break;
          case 'users':
            listUserTreeByDeptIds({deptIds: this.transferCurrent.deptIds}).then((res) => {
              this.loading = false
              this.data = res.data.data;
              this.buildLabelCache(this.data);
            });
            break;
          case 'auditUser':
            listAuditUserTree().then((res) => {
              this.loading = false
              this.data = res.data.data.map(item => {
                const filteredChildren = item.children.filter(child => child.status !== "12");
                return {
                  ...item, // 展开原始 item 的所有属性（除了 children）
                  children: filteredChildren // 替换为过滤后的 children
                };
              });
              this.buildLabelCache(this.data);
            });
            break;
          case 'auditedUser':
            listAuditedUserTree().then((res) => {
              this.handleExpand(false)
              this.loading = false
              this.data = res.data.data;
              this.buildLabelCache(this.data);
            });
            break;
          case 'developer':
            fetchTreeByTypes({types: this.transferCurrent.types}).then((res) => {
              this.loading = false
              this.data = res.data.data;
              this.buildLabelCache(this.data);
            });
            break;
          case 'contacts':
            listUserTreeByJobCategory({jobCategory: this.transferCurrent.jobCategory}).then((res) => {
              this.handleExpand(false)
              this.loading = false
              this.data = res.data.data;
              this.buildLabelCache(this.data);
            });
            break;
        }
        if (this.transferCurrent && this.transferCurrent.currentval) {
          if (this.transferCurrent.currentval.length > 0) {
            this.teamActiveList = this.transferCurrent.currentval.filter(item => item !== '' && item !== undefined && item !== null && item !== [] && item !== {});
          }
          let currentId = []
          this.teamActiveList.forEach(item => {
            currentId.push(item.id)
          })
          if (currentId.length > 0) {
            this.$nextTick(()=>{
              this.defaultExpandedKeys = currentId;
            })
          }
          this.$nextTick(()=>{
            this.$refs.tree.setCheckedKeys(currentId);
          })
        }
      }
    },
  },
  methods: {
    // 构建缓存
    buildLabelCache(nodes, path = []) {
      nodes.forEach(node => {
        const currentPath = [...path, node.name];
        if (node.id) {
          this.labelCache[node.id] = currentPath;
        }
        if (node.children && node.children.length > 0) {
          this.buildLabelCache(node.children, currentPath);
        }
      });
    },

    // 检索
    handleFilter(){
      if (!this.filterText || this.filterText.trim() === ''){
        this.handleExpand(false)
      }
      this.$refs.tree.filter(this.filterText);
    },
    // 重置检索
    filterReset(){
      this.filterText = '';
      this.handleExpand(false)
      this.$refs.tree.filter();
    },
    filterNode(value, data) {
      if (!value) return true;
      const nodePath = this.labelCache[data.id];
      if (Array.isArray(nodePath) && nodePath.every(label => typeof label === 'string')) {
        return nodePath.some(label => label.includes(value));
      }
      return false;
    },
    // 是否展开所有节点
    handleExpand(val){
      this.isExpand = val;
      this.refreshTable = false;
      this.$nextTick(() => {
        this.refreshTable = true
      });
    },

    // 添加
    createNodeMap(nodes) {
      let nodeMap = new Map();
      nodes.forEach(node =>{
        // 将该节点下的所有子节点存储进映射
        this.getChildrenNodes(node, nodeMap);
        nodeMap.set(node.id, node);
      })
      return nodeMap;
    },

    getChildrenNodes(node, nodeMap) {
      if (node.children && node.children.length > 0) {
        node.children.forEach(child => {
          nodeMap.set(child.id, child);
          // 如果当前节点有子孙节点，则递归处理
          if (child.children && child.children.length > 0) {
            this.getChildrenNodes(child, nodeMap);
          }
        })
      }
    },

    // 检查当前节点的根节点是否已被添加
    isAncestorAdded(node, addedNodeIds, nodeMap) {
      if (!node.parentId) {
        return false;
      }
      const parent = nodeMap.get(node.parentId);
      if (!parent) {
        return false;
      }
      if (addedNodeIds.has(parent.id)) {
        return true;
      }
      // 递归检查祖先节点
      return this.isAncestorAdded(parent, addedNodeIds, nodeMap);
    },

    // 更新节点的名称，将其父节点的名称作为前缀
    updateNodeNameWithParent(node, parent) {
      if (parent && !node.name.includes(parent.name) && !parent.disabled) {
        return `${parent.name} / ${node.name}`;
      }
      return node.name
    },

    // 处理选中的节点，将其添加到最终列表中，并更新其名称（如果需要）
    processCheckedNode(node, nodeMap, addedNodeIds, finalList) {
      const isAncestorAdded = this.isAncestorAdded(node, addedNodeIds, nodeMap);
      if (!node.disabled) {
        if (!isAncestorAdded && !addedNodeIds.has(node.id)) {
          // 对节点进行拷贝
          const copiedNode = { ...node };

          // 更新节点的名称
          let parent = nodeMap.get(copiedNode.parentId);
          while (parent) {
            copiedNode.name = this.updateNodeNameWithParent(copiedNode, parent);
            parent = nodeMap.get(parent.parentId);
          }

          // 将拷贝后的节点添加到 finalList
          finalList.push(copiedNode);
          addedNodeIds.add(node.id);
        }
      }
    },

    validateSelection(data, check) {
      const checkedNodes = this.$refs.tree.getCheckedNodes();
      const addedNodeIds = new Set(); // 记录已添加到最终列表中的节点ID
      const finalList = []; // 最终要保留的节点列表

      if (!this.nodeMap.size > 0){
        this.nodeMap = this.createNodeMap(this.data); // 创建节点映射
      }

      if (this.multiple){
        // 遍历所有选中的节点
        checkedNodes.forEach(node => {
          this.processCheckedNode(node, this.nodeMap, addedNodeIds, finalList);
        });
        this.teamActiveList = finalList;
      } else {
        if (check){
          this.processCheckedNode(data, this.nodeMap, addedNodeIds, finalList);
          this.$refs.tree.setCheckedKeys([data.id]);
          this.teamActiveList = [finalList[0]];
        } else if (this.teamActiveList.length > 0 && data.id === this.teamActiveList[0].id){
          this.teamActiveList = []
        }
      }
      // console.log('验证后的列表:', this.teamActiveList);
    },

    teamActiveListClick(row) { // 已选择
      this.teamActiveCurrent = row.id
    },

    removeDblclickItem() {
      const indexToRemove = this.teamActiveList.findIndex(item => item.id === this.teamActiveCurrent);

      if (indexToRemove !== -1) {
        this.teamActiveList.splice(indexToRemove, 1);
        const currentIds = this.teamActiveList.map(item => item.id);
        this.$refs.tree.setCheckedKeys(currentIds);
      }
    },

    clearTeamActiveList(){
      this.teamActiveList = []
      this.teamActiveCurrent = ''
      this.$refs.tree.setCheckedKeys([])
    },

    moveClick(name) {
      if (name === 'top') {
        let index = 0
        this.teamActiveList.forEach((item, i) => {
          if (item.id === this.teamActiveCurrent) index = i
        })
        if (index > 0) {
          // 在上一项插入该节点
          this.teamActiveList.splice(index - 1, 0, (this.teamActiveList[index]))
          // 移除该节点
          this.teamActiveList.splice(index + 1, 1)
        }
      }
      if (name === 'bottom') {
        let index = 0
        this.teamActiveList.forEach((item, i) => {
          if (item.id === this.teamActiveCurrent) index = i
        })

        if (index >= 0) {
          // 在下一项插入该节点
          this.teamActiveList.splice(index + 2, 0, (this.teamActiveList[index]))
          // 移除该节点
          this.teamActiveList.splice(index, 1)
        }
      }
      let currentId = []
      this.teamActiveList.forEach((item) => {
        currentId.push(item.id)
      })
      if (currentId.length > 0) this.$refs.tree.setCheckedKeys(currentId);
    },
    confirm() {
      this.$emit('transferData', {
        transferDialog: false,
        list: this.teamActiveList
      })
      this[this.transferType+ 'ActiveList'] = this.teamActiveList;
      this.teamActiveList = []
      this.nodeMap = new Map();
    },
    // 关闭页面时将选中的数据清空
    cancelDialog() {
      this.$emit('closeTransfer')
      this.data = [];
      this.teamList = [];
      this.teamActiveList = [];
      this.nodeMap = new Map();
      this.handleExpand(true)
      this.filterText = ''
      this.$refs.tree.setCheckedKeys([])
    },
  }
}
</script>

<style lang="scss" scoped>
.teamList {
  border-bottom: 1px solid #409EFF;
  display: flex;
  margin-bottom: 15px;
  li {
    list-style: none;
    min-width: 60px;
    padding: 0 10px 5px;
    font-size: 13px;
    text-align: center;
    &.current {
      border-bottom: 2px solid #409EFF;
    }
  }
}
/deep/ .transferForm {
  background: #f5f5f5;
  border-top: 5px solid #409EFF;
  .el-dialog__header {
    border-bottom: 1px solid #dedede;
  }
  .el-dialog__title {
    font-size: 15px;
    color: #999999;
  }
  .el-dialog__body {
    padding-top: 10px;
  }
  .transferForm-box {
    display: flex;
    height: 400px;
    .transferLeft {
      width: calc(55% - 80px);
      margin-right: 80px;
    }
    .transferRight {
      width: calc(45% - 80px);
      height: 100%;
    }
    .transferArrow {
      width: 80px;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      .arrowIcon {
        width: 30px;
        height: 30px;
        margin: 10px 0;
        background: #b4ccd5;
        border-radius: 50%;
        color: #ffffff;
        font-size: 18px;
        font-weight: bolder;
        display: flex;
        justify-content: center;
        align-items: center;
        &:hover {
          background-color: #409EFF;
        }
      }
    }
    .transferBox {
      border: 1px solid #cccccc;
      background-color: #ffffff;
      .transferBox-title {
        display: flex;
        align-items: center;
        height: 40px;
        padding: 0 10px;
        background-color: #e4e4e4;
        .selectFilter {
          display: flex;
          align-items: center;
          justify-content: space-between;
          .text {
            width: 80%;
            text-overflow: ellipsis;
            overflow: hidden;
            white-space: nowrap;
          }
        }
      }
      .transferBox-con {
        width: 100%;
        height: calc(100% - 40px);
        padding: 5px 10px;
        overflow-y: scroll;
        font-size: 13px;
        .current {
          background-color: rgba($color: #409EFF, $alpha: 0.4);
        }
        .el-col {
          text-overflow: ellipsis;
          overflow: hidden;
          white-space: nowrap;
          margin: 0;
        }
      }
    }
  }
}
</style>
